package cn.song.freight.service;

import cn.song.freight.domain.dto.FreightCalculationRequestDTO;
import cn.song.freight.domain.dto.FreightCalculationResponseDTO;

/**
 * 运费计算服务接口（统一版本）
 * <pre>
 * 该服务接口定义了物流系统的核心运费计算功能，实现了接口统一和层级匹配优化。
 * 支持自动策略选择和手动策略指定两种模式，提供精确的运费计算能力。
 *
 * 核心特性：
 * 1. 统一接口设计：将原有的两个接口合并为一个，支持可选策略ID参数
 * 2. 智能策略选择：基于仓库编码、物流公司编码和区域信息自动选择最优策略
 * 3. 层级地区匹配：实现精确ID > 区县 > 城市 > 省份的优先级匹配算法
 * 4. 多重定价模型：支持首重续重模式和重量区间模式两种定价策略
 * 5. 抛重计算优化：基于可配置抛重比进行精确的体积重量计算
 *
 * 策略选择优先级：
 * 1. 手动指定策略：当request.strategyId不为空时，直接使用指定策略
 * 2. 客户专用分配：基于仓库编码和物流公司编码的特定策略分配
 * 3. 区域专用映射：通过PricingAreaMapping表进行地区层级匹配
 * 4. 默认活跃策略：作为兜底策略使用系统默认的活跃策略
 *
 * 地区匹配算法：
 * - 精确匹配：直接使用提供的区域ID进行匹配
 * - 区县级匹配：使用省份+城市+区县的完整地址信息
 * - 城市级匹配：使用省份+城市的地址信息进行匹配
 * - 省份级匹配：仅使用省份信息进行匹配
 * - 层级回退：当精确匹配失败时，自动向上级地区回退匹配
 *
 * 定价模型说明：
 * - 模式1（首重续重）：基础重量费用 + 超出部分按续重单位计费
 * - 模式2（重量区间）：根据重量区间规则应用固定费率
 *
 * @author SongRenShuo
 * @version 3.0.0
 * @since 2025-08-23
 */
public interface FreightCalculationService {

    /**
     * 统一运费计算接口（支持自动策略选择和手动策略指定）
     * <pre>
     * 该方法是系统的核心计算接口，支持两种计算模式：
     *
     * 模式1 - 自动策略选择（推荐）：
     * 当request.strategyId为null时，系统将基于以下优先级自动选择最优策略：
     * Ⅰ 客户专用策略：根据仓库编码和物流公司编码查找专属策略分配
     * Ⅱ 区域专用策略：通过目的地区域信息匹配适用的策略映射
     * Ⅲ 默认活跃策略：使用系统配置的默认策略作为兜底方案
     *
     * 模式2 - 手动策略指定：
     * 当request.strategyId有值时，直接使用指定的策略进行计算
     * 系统会验证策略的有效性和活跃状态
     *
     * 核心处理流程：
     * 1. 请求参数验证：检查必要的重量、尺寸和目的地信息
     * 2. 策略确定阶段：根据上述两种模式确定要使用的计费策略
     * 3. 目标区域解析：将地址信息转换为标准的区域ID
     * 4. 定价配置获取：应用层级匹配算法获取适用的定价配置
     * 5. 重量计算处理：计算实际重量、抛重和最终计费重量
     * 6. 费用计算执行：根据定价模型（首重续重/重量区间）计算费用
     * 7. 结果封装返回：生成包含详细明细的计算结果
     *
     * 层级匹配优化：
     * 在获取定价配置时，系统采用智能的层级匹配算法：
     * - 优先级1：精确区域ID匹配（最高优先级）
     * - 优先级2：区县级匹配（省份+城市+区县）
     * - 优先级3：城市级匹配（省份+城市）
     * - 优先级4：省份级匹配（仅省份）
     * 这确保了即使目标区域没有专门配置，也能通过上级区域的配置提供服务
     *
     * 计费重量计算：
     * 系统会同时计算实际重量和抛重（体积重量），取较大值作为计费重量：
     * - 实际重量：直接使用请求中提供的重量值
     * - 抛重计算：长×宽×高（厘米）÷ 抛重比率
     * - 计费重量：max(实际重量, 抛重)
     *
     * @param request 运费计算请求对象，包含以下核心信息：
     *                - weight: 包裹实际重量（必需）
     *                - length/width/height: 包裹尺寸（用于抛重计算）
     *                - toAreaId: 目标区域ID（可选，与地址信息二选一）
     *                - toProvinceName/toCityName/toDistrictName: 目标地址信息
     *                - warehouseCode: 仓库编码（用于策略选择）
     *                - logisticsCompanyCode: 物流公司编码（用于策略选择）
     *                - strategyId: 指定策略ID（可选，指定时使用手动模式）
     * @return FreightCalculationResponseDTO 详细的运费计算结果，包含：
     *         - freight: 最终运费金额
     *         - actualWeight/volumetricWeight/chargeableWeight: 各种重量信息
     *         - strategyId/strategyName: 使用的策略信息
     *         - pricingModel: 使用的定价模型（1=首重续重，2=重量区间）
     *         - calculationDetail: 详细的计算过程说明
     *         - 其他相关的计算明细信息
     * @throws IllegalArgumentException 当必需参数缺失或格式无效时抛出
     * @throws RuntimeException 当系统无法找到适用策略或定价配置时抛出
     * @since 1.0.0 初始版本，支持基础的自动策略选择
     * @since 2.0.0 增加手动策略指定功能
     * @since 3.0.0 接口统一，优化层级匹配算法
     */
    FreightCalculationResponseDTO calculateFreight(FreightCalculationRequestDTO request);


}
